﻿namespace EFS.RC.CC.Presences.Operators.OfficeService.Supervisors
{
	internal class Supervisor : EFS.RC.CC.Presences.Operators.Deployment<EFS.RC.CC.Deployment.Entities.Operators.Supervisor>
	{
		#region Composition

		/// Sync access
		private object syncAccess = new object();

		/// Operator central application
		private EFS.RC.CC.Applications.Remote.Operators.SupervisorCentral supervisorCentralApplication = null;

		/// Monitoring session
		private EFS.RC.CC.Sessions.OfficeService.Operators.Supervisors.Monitoring supervisorMonitoringSession = null;

		#endregion

		#region Constructor

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="supervisor"></param>
		public Supervisor(EFS.RC.CC.Deployment.Entities.Operators.Supervisor supervisor, EFS.RC.CC.Applications.EndPoints.OfficeService.Operators operatorsOfficeServiceEndPointApplication)
			: base(supervisor, operatorsOfficeServiceEndPointApplication)
		{
		}

		#endregion

		#region Usage

		/// <summary>
		/// Application
		/// </summary>
		public EFS.RC.CC.Applications.Remote.Operators.SupervisorCentral SupervisorCentralApplication
		{
			get { return supervisorCentralApplication; }
		}

		/// <summary>
		/// End point model
		/// </summary>
		public EFS.RC.CC.Sessions.OfficeService.Operators.Supervisors.Monitoring SupervisorMonitoringSession
		{
			get
			{
				// ~ commented for performance ~  EFS.EventLog.Log.LogExtended("Entering lock", new System.Diagnostics.StackTrace());
				lock (syncAccess)
				{
					// check
					EFS.Common.Verify.Reference(supervisorMonitoringSession, "Supervisor Monitoring Session not Created");

					// done
					return supervisorMonitoringSession;
				}
			}
		}

		/// <summary>
		/// Start central app
		/// </summary>
		/// <param name="supervisorInstantMessagingCall"></param>
		/// <param name="operatorsTeam"></param>
		public void StartSupervisorCentralApplication(
			Microsoft.Rtc.Collaboration.InstantMessagingCall supervisorInstantMessagingCall,
			EFS.RC.CC.Presences.Operators.OfficeService.Team operatorsTeam)
		{
			// sync access
			// ~ commented for performance ~  EFS.EventLog.Log.LogExtended("Entering lock", new System.Diagnostics.StackTrace());
			lock (syncAccess)
			{
				// verify existing and shutdown
				if (null != this.supervisorCentralApplication)
				{
					// already started
					throw new System.InvalidOperationException("Supervisor Central Application already started");
				}

				try
				{
					// make application
					this.supervisorCentralApplication = new EFS.RC.CC.Applications.Remote.Operators.SupervisorCentral(this, supervisorInstantMessagingCall, operatorsTeam);
					this.supervisorCentralApplication.AsinkTerminatedDelegate.Register(CentralApplicationTerminated);

					// startup
					this.supervisorCentralApplication.BeginStartup();
				}
				catch (System.Exception ex)
				{
					// log
					EFS.EventLog.Log.LogException(ex, this);

					// cleanup
					this.supervisorCentralApplication = null;
				}
			}
		}

		/// <summary>
		/// Start supervisor session
		/// </summary>
		public void StartSupervisorSession(EFS.RC.CC.Confereces.OfficeService officeServiceConference)
		{
			// check
			EFS.Common.Verify.Reference(officeServiceConference, "officeServiceConference");

			// sync access
			// ~ commented for performance ~  EFS.EventLog.Log.LogExtended("Entering lock", new System.Diagnostics.StackTrace());
			lock (syncAccess)
			{
				// verify existing and shutdown
				if (this.supervisorMonitoringSession != null)
				{
					throw new System.InvalidOperationException("Supervisor Monitoring Session already started");
				}

				try
				{
					// make session
					this.supervisorMonitoringSession = new EFS.RC.CC.Sessions.OfficeService.Operators.Supervisors.Monitoring(officeServiceConference, this);
					this.supervisorMonitoringSession.AsinkTerminatedDelegate.Register(OnSessionTerminated);
					this.supervisorMonitoringSession.BeginStartup();
				}
				catch (System.Exception ex)
				{
					// log
					EFS.EventLog.Log.LogException(ex, this);

					// remove
					this.supervisorMonitoringSession = null;
				}
			}
		}

		/// <summary>
		/// Describe this object into a nice formated string
		/// </summary>
		/// <returns></returns>
		public override System.String Describe()
		{
			return System.String.Format("EFS.RC.CC.Presences.Operators.OfficeService.Supervisors.Supervisor [{0}]", base.Describe());
		}

		#endregion

		#region Runtime

		/// <summary>
		/// Application
		/// </summary>
		private void CentralApplicationTerminated(EFS.RC.CC.Applications.Remote.Messaging remoteMessagingApplication)
		{
			// sync access
			// ~ commented for performance ~  EFS.EventLog.Log.LogExtended("Entering lock", new System.Diagnostics.StackTrace());
			lock (syncAccess)
			{
				// app is SC
				EFS.RC.CC.Applications.Remote.Operators.SupervisorCentral supervisorCentralApplication = remoteMessagingApplication as EFS.RC.CC.Applications.Remote.Operators.SupervisorCentral;

				// check if we have any
				if (null == this.supervisorCentralApplication || !this.supervisorCentralApplication.Equals(supervisorCentralApplication))
				{
					// different
					throw new System.InvalidOperationException("Terminated Supervisor Central Application is different");
				}

				// unregister
				this.supervisorCentralApplication = null;
			}
		}

		/// <summary>
		/// Supervisor session terminated
		/// </summary>
		/// <param name="supervisorMonitoringSession"></param>
		private void OnSessionTerminated(EFS.RC.CC.Sessions.OfficeService.IParticipant officeServiceSessionParticipant)
		{
			// log
			EFS.EventLog.Log.LogInfo("OnSupervisorSessionTerminated", this);

			// check
			EFS.Common.Verify.Reference(officeServiceSessionParticipant, "officeServiceSessionParticipant");

			// cast
			EFS.RC.CC.Sessions.OfficeService.Operators.Supervisors.Monitoring supervisorMonitoringSession = officeServiceSessionParticipant as EFS.RC.CC.Sessions.OfficeService.Operators.Supervisors.Monitoring;

			// check
			EFS.Common.Verify.Reference(supervisorMonitoringSession, "supervisorMonitoringSession");

			// sync access
			// ~ commented for performance ~  EFS.EventLog.Log.LogExtended("Entering lock", new System.Diagnostics.StackTrace());
			lock (syncAccess)
			{
				// check if we have any
				if (null == this.supervisorMonitoringSession || !supervisorMonitoringSession.Equals(supervisorMonitoringSession))
				{
					// different
					throw new System.InvalidOperationException("Terminated Supervisor Monitorring Session is different");
				}

				// unregister
				this.supervisorMonitoringSession = null;
			}
		}

		#endregion
	}
}
